package net.fdukedom.epicurus.security;

import net.fdukedom.epicurus.domain.entity.AccessRule;
import net.fdukedom.epicurus.domain.entity.User;

import java.util.*;

/**
 * @author Dmitry Y. Kochelaev
 */
public class AccessChecker {

    /**
     * Instance of class.
     */
    private static final AccessChecker instance = new AccessChecker();

    /**
     * Utility class.
     */
    private AccessChecker() {
    }

    /**
     * Returns instance of the class.
     *
     * @return instance of the class
     */
    public static AccessChecker getInstance() {
        return instance;
    }

    /**
     * Access rules map. ActionName -- AccessRule.
     */
    private Map<String, List<AccessRule>> rules = new HashMap<String, List<AccessRule>>();

    /**
     * Adds access rule.
     *
     * @param rule rule to be added
     */
    public void addRule(AccessRule rule) {
        List<AccessRule> accessRules = rules.get(rule.getAction().getName());
        if (accessRules == null) {
            accessRules = new ArrayList<AccessRule>();
            rules.put(rule.getAction().getName(), accessRules);
        }
        accessRules.add(rule);
    }

    /**
     * Adds list of rules.
     *
     * @param rules rules to be added
     */
    public void addRules(Collection<AccessRule> rules) {
        for (AccessRule rule : rules) {
            addRule(rule);
        }
    }

    /**
     * Checks if user has access of specified type to specified action.
     *
     * @param user user to be checked
     * @param actionName action to be checked
     * @param accessType required access type
     *
     * @return if user has access
     */
    public boolean hasAccess(User user, String actionName, int accessType) {
        List<AccessRule> accessRules = rules.get(actionName);
        if (accessRules == null) {
            return false;
        }
        for (AccessRule rule : accessRules) {
            if (rule.getAccessType() == accessType) {
                if (user.getGroups().contains(rule.getGroup())) {
                    return true;
                }
            }
        }
        return false;
    }
}

